using MicroMsg.Common.Pointer;
using System;
namespace MicroMsg.Common.Algorithm
{
	public class RSA
	{
		public const int RBCPR_OK = 0;
		public const int RBCPR_ERR_GENERAL = 1;
		public const int RBCPR_ERR_INVALID_ARG = 2;
		public const int RBCPR_ERR_PACK_CORRUPTED = 3;
		public const int RBCPR_ERR_UNSUPPORTED_VERSION = 4;
		public const int RBCPR_ERR_UNSUPPORTED_ALGORITHM = 5;
		public const int RBCPR_ERR_INVALID_RSA_KEY_N = 6;
		public const int RBCPR_ERR_INVALID_RSA_KEY_E = 7;
		public const int RBCPR_ERR_ENCRYPT_WITH_RSA_PUBKEY = 8;
		public const int RBCPR_ERR_LOAD_RSA_PRIVATE_KEY = 9;
		public const int RBCPR_ERR_DECRYPT_WITH_RSA_PRIVKEY = 10;
		public const int RBCPR_ERR_ENCRYPT_WITH_DES_KEY = 11;
		public const int RBCPR_ERR_DECRYPT_WITH_DES_KEY = 12;
		public const int RBCPR_ERR_NO_REFERENCE_INFO = 13;
		public const int RBCPR_ERR_NO_MEMORY = 14;
		public const int RBCPR_ERR_NO_SEQ = 15;
		public const int XYSSL_ERR_RSA_BAD_INPUT_DATA = -1024;
		public const int XYSSL_ERR_RSA_INVALID_PADDING = -1040;
		public const int XYSSL_ERR_RSA_KEY_GEN_FAILED = -1056;
		public const int XYSSL_ERR_RSA_KEY_CHECK_FAILED = -1072;
		public const int XYSSL_ERR_RSA_PUBLIC_FAILED = -1088;
		public const int XYSSL_ERR_RSA_PRIVATE_FAILED = -1104;
		public const int XYSSL_ERR_RSA_VERIFY_FAILED = -1120;
		public const int RSA_RAW = 0;
		public const int RSA_MD2 = 2;
		public const int RSA_MD4 = 3;
		public const int RSA_MD5 = 4;
		public const int RSA_SHA1 = 5;
		public const int RSA_SHA256 = 6;
		public const int RSA_PUBLIC = 0;
		public const int RSA_PRIVATE = 1;
		public const int RSA_PKCS_V15 = 0;
		public const int RSA_PKCS_V21 = 1;
		public const int RSA_SIGN = 1;
		public const int RSA_CRYPT = 2;
		public const string KEY_E = "010001";
		public static string KEY_N = "DFE56EEE6506E5F9796B4F12C3A48121B84E548E9999D834E2C037E3CD276E9C4A2B1758C582A67F6D12895CE5525DDE51D0B92D32B8BE7B2C85827729C3571DCC14B581877BC634BCC7F9DA3825C97A25B341A64295098303C4B584EC579ECCA7C8B96782F65D650039EE7A0772C195DBEFC4488BDFB0B9A58C5C058E3AB04D";
		private static bool INIT_BIGNUM_TABLE = false;
		private static BigInteger[] bigNumTable = null;
		private static void initBigNumTable()
		{
			RSA.INIT_BIGNUM_TABLE = true;
			RSA.bigNumTable = new BigInteger[1024];
			RSA.bigNumTable[0] = BigInteger.ONE;
			RSA.bigNumTable[1] = new BigInteger("2");
			for (int i = 2; i < 1024; i++)
			{
				RSA.bigNumTable[i] = RSA.bigNumTable[i - 1].multiply(RSA.bigNumTable[1]);
			}
		}
		private static BigInteger mpiToBigInteger(MPI mpi_0)
		{
			BigInteger bigInteger = BigInteger.ZERO;
			for (int i = 0; i < mpi_0.int_1; i++)
			{
				byte[] bval = TypeTransform.longToByteArrayHL(mpi_0.plongArray_0.value_[i]);
				BigInteger bigInteger2 = new BigInteger(bval);
				bigInteger = bigInteger.vmethod_1(bigInteger2.multiply(RSA.bigNumTable[BigNum.biL * i]));
			}
			return bigInteger;
		}
		private static MPI bigIntegerToMpi(BigInteger bigNum)
		{
			byte[] array = bigNum.toByteArray();
			MPI mPI = new MPI();
			mPI.int_0 = 1;
			mPI.int_1 = (array.Length + BigNum.ciL - 1) / BigNum.ciL;
			mPI.plongArray_0.value_ = new long[mPI.int_1];
			byte[] array2 = new byte[mPI.int_1 * BigNum.ciL];
			Arrays.fill(array2, 0);
			Array.Copy(array, 0, array2, mPI.int_1 * BigNum.ciL - array.Length, array.Length);
			byte[] array3 = new byte[8];
			int num = 0;
			for (int i = mPI.int_1 - 1; i >= 0; i--)
			{
				for (int j = 0; j < 8; j++)
				{
					if (j < 8 - BigNum.ciL)
					{
						array3[j] = 0;
					}
					else
					{
						array3[j] = array2[num++];
					}
				}
				mPI.plongArray_0.value_[i] = TypeTransform.byteArrayHLToLong(array3);
			}
			return mPI;
		}
		public static int rsaPublic(RsaContext rsaContext_0, PByteArray pbaInput, PByteArray pbaOutput)
		{
			MPI mpi_ = new MPI();
			if (!RSA.INIT_BIGNUM_TABLE)
			{
				RSA.initBigNumTable();
			}
			int num = BigNum.mpiReadBinary(mpi_, pbaInput);
			if (num != 0)
			{
				return num;
			}
			if (BigNum.mpiCmpMpi(mpi_, rsaContext_0.N) >= 0)
			{
				return -1024;
			}
			BigInteger bigInteger = RSA.mpiToBigInteger(mpi_);
			BigInteger exponent = RSA.mpiToBigInteger(rsaContext_0.E);
			BigInteger bigInteger_ = RSA.mpiToBigInteger(rsaContext_0.N);
			BigInteger bigNum = bigInteger.modPow(exponent, bigInteger_);
			mpi_ = RSA.bigIntegerToMpi(bigNum);
			if (num != 0)
			{
				return num;
			}
			return BigNum.mpiWriteBinary(mpi_, pbaOutput);
		}
		public static int encryptSection(RsaContext rsaContext_0, int mode, int iLen, int startIdx, byte[] plainText, PByteArray pbaOutput)
		{
			int int_ = rsaContext_0.int_1;
			pbaOutput.value_ = new byte[rsaContext_0.int_1];
			int num = 0;
			int padding = rsaContext_0.padding;
			if (padding != 0)
			{
				return -1040;
			}
			if (iLen < 0 || int_ < iLen + 11)
			{
				return -1024;
			}
			int num2 = int_ - 3 - iLen;
			pbaOutput.value_[num++] = 0;
			pbaOutput.value_[num++] = 2;
			Random random = new Random();
			while (num2-- > 0)
			{
				do
				{
					pbaOutput.value_[num] = (byte)random.Next();
				}
				while (pbaOutput.value_[num] == 0);
				num++;
			}
			pbaOutput.value_[num++] = 0;
			for (int i = startIdx; i < startIdx + iLen; i++)
			{
				pbaOutput.value_[num++] = plainText[i];
			}
			PByteArray pByteArray = new PByteArray();
			pByteArray.value_ = new byte[rsaContext_0.int_1];
			Array.Copy(pbaOutput.value_, 0, pByteArray.value_, 0, pbaOutput.value_.GetLength(0));
			if (mode == 0)
			{
				return RSA.rsaPublic(rsaContext_0, pByteArray, pbaOutput);
			}
			return 0;
		}
		public static int RSAEncrypt(out byte[] encryptText, byte[] plainText)
		{
			encryptText = null;
			if (plainText == null)
			{
				return 2;
			}
			RsaContext rsaContext = new RsaContext();
			rsaContext.init(0, 0);
			int num = BigNum.mpiReadString(rsaContext.N, 16, RSA.KEY_N);
			if (num != 0)
			{
				return 6;
			}
			num = BigNum.mpiReadString(rsaContext.E, 16, "010001");
			if (num != 0)
			{
				return 7;
			}
			rsaContext.int_1 = BigNum.mpiMsb(rsaContext.N) + 7 >> 3;
			PByteArray pByteArray = new PByteArray();
			int num2 = plainText.Length;
			int num3 = num2 / (rsaContext.int_1 - 12);
			if (num2 % (rsaContext.int_1 - 12) != 0)
			{
				num3++;
			}
			encryptText = new byte[num3 * rsaContext.int_1];
			if (num2 >= rsaContext.int_1 - 12)
			{
				for (int i = 0; i < num3; i++)
				{
					int iLen = rsaContext.int_1 - 12;
					if (i == num3 - 1)
					{
						iLen = num2 - i * (rsaContext.int_1 - 12);
					}
					if (RSA.encryptSection(rsaContext, 0, iLen, i * (rsaContext.int_1 - 12), plainText, pByteArray) != 0)
					{
						return 8;
					}
					Array.Copy(pByteArray.value_, 0, encryptText, i * rsaContext.int_1, rsaContext.int_1);
				}
			}
			else
			{
				num = RSA.encryptSection(rsaContext, 0, num2, 0, plainText, pByteArray);
				if (num != 0)
				{
					return 8;
				}
				Array.Copy(pByteArray.value_, 0, encryptText, 0, rsaContext.int_1);
			}
			return 0;
		}
	}
}
